package com.audaque.springboot.foshanupload.casclientautoconfigsupport.interceptor;


import com.audaque.springboot.foshanupload.authcore.model.currentUser.TransmittableThreadLocalCurrentUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jasig.cas.client.authentication.AttributePrincipal;
import org.jasig.cas.client.util.AbstractCasFilter;
import org.jasig.cas.client.validation.Assertion;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.security.Principal;
import java.util.Map;

/**
 * @author zgb
 * @desc 父子线程传递上下文（用户信息）
 * @date 2022-05-09 10:57:23
 */
//通过配置order()的值，值越小，优先级越高。不配默认是0
//在 SessionInterceptor后，避免逻辑重复
@Slf4j
@Order(2)
public class TransmittableThreadLocalInterceptor extends HandlerInterceptorAdapter {

    @Value("${db.tenantId}")
    private String tenantId;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.debug("ThreadId:" + Thread.currentThread().getId());
        log.debug("ThreadName:" + Thread.currentThread().getName());
        //保存当前用户信息到父子线程
        TransmittableThreadLocalCurrentUser transmittableThreadLocalCurrentUser = new TransmittableThreadLocalCurrentUser();
        HttpSession httpSession = request.getSession();
        if(httpSession!=null){
            String sessionId = httpSession.getId();
            log.debug("sessionId:" + sessionId);

            //方式1
            //SSO session:key="_const_cas_assertion_" value=assertion对象
            //这个是CAS客户端拿着ticket去server认证后存储的用户信息，是客户端存储的SSO会话。只要拿不到这个session，就必须重定向去登录
            Assertion assertion = (Assertion) httpSession.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
            //方式2
            //Assertion assertion = AssertionHolder.getAssertion();


            TransmittableThreadLocalCurrentUser currentUser = TransmittableThreadLocalCurrentUser.getCurrentUser();

            if (assertion != null && assertion.getPrincipal() != null && StringUtils.isNotBlank(assertion.getPrincipal().getName())) {
                Principal principal = assertion.getPrincipal();
                transmittableThreadLocalCurrentUser.setUsername(principal.getName());
                transmittableThreadLocalCurrentUser.setTenantId(tenantId);


                if (principal instanceof AttributePrincipal) {
                    //cas传递过来的数据
                    Map<String, Object> result = ((AttributePrincipal) principal).getAttributes();
                    for (Map.Entry<String, Object> entry : result.entrySet()) {
                        String key = entry.getKey();
                        Object val = entry.getValue();
                        log.debug("%s:%s\r\n", key, val);//credentialType:UsernamePasswordCredential
                    }
                }
            } else {
                transmittableThreadLocalCurrentUser = null;
            }

        } else {
            transmittableThreadLocalCurrentUser = null;
        }




        //转传，避免重复解析用户
        TransmittableThreadLocalCurrentUser.setCurrentUser(transmittableThreadLocalCurrentUser);
        log.debug("transmittableThreadLocalCurrentUser:" + transmittableThreadLocalCurrentUser);
        return true;
    }
}
